#include "TcpServerSender.h"
#include <boost/asio.hpp>

TcpServerSender::TcpServerSender(const std::string &listenIP, unsigned short listenPort)

{
    boost::asio::ip::tcp::endpoint endpoint =
        listenIP.empty() ? boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), listenPort)
                         : boost::asio::ip::tcp::endpoint(boost::asio::ip::make_address(listenIP), listenPort);
    io_context_ = std::make_unique<boost::asio::io_context>();

    acceptor_ = std::make_unique<boost::asio::ip::tcp::acceptor>(*io_context_, endpoint);
    acceptor_->set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
    acceptor_->listen();
}

TcpServerSender::~TcpServerSender()
{
    ;
}

void TcpServerSender::startAccept()
{
    std::lock_guard<std::mutex> lock(client_mutex_);
    auto socket = std::make_shared<boost::asio::ip::tcp::socket>(*io_context_);
    acceptor_->async_accept(*socket, [this, socket](boost::system::error_code ec)
                            {
            if (!ec) {                
                if (socket->is_open())
                {
                    clients_.push_back(socket);
                                    std::cout << "Accepted connection from: "
                                    << socket->remote_endpoint().address().to_string()
                                    << ":" << socket->remote_endpoint().port() << std::endl;
                                startAccept();
                }            
            } });
}

void TcpServerSender::start()
{
    if (running_)
        return;

    startAccept();
    running_ = true;
    io_thread_ = std::thread([this]()
                             { io_context_->run(); });
}

bool TcpServerSender::send(const std::stringstream &stream)
{
    std::lock_guard<std::mutex> lock(client_mutex_);
    for (auto &socket : clients_)
    {
        if (socket->is_open())
        {
            try
            {
                const std::string& data=stream.str();

                // 添加帧头
                uint32_t frame_size = htonl(data.size());
                boost::asio::write(*socket, boost::asio::buffer(&frame_size, 4));

                // 发送数据
                boost::asio::write(*socket,boost::asio::buffer(data));
            }
            catch (const boost::system::system_error &) // e)
            {
                removeClient(socket);
            }
        }
    }

    return true;
}

bool TcpServerSender::send(std::vector<uint8_t> buffer)
{
    std::lock_guard<std::mutex> lock(client_mutex_);
    for (auto &socket : clients_)
    {
        if (socket->is_open())
        {
            try
            {
                boost::asio::write(*socket, boost::asio::buffer(buffer));
            }
            catch (const boost::system::system_error &) // e)
            {
                removeClient(socket);
            }
        }
    }

    return true;
}

void TcpServerSender::stop()
{
    if (!running_)
        return;

    running_ = false;
    io_context_->stop();
    if (io_thread_.joinable())
    {
        io_thread_.join();
    }
}

void TcpServerSender::removeClient(std::shared_ptr<boost::asio::ip::tcp::socket> socket)
{
    auto it = std::find(clients_.begin(), clients_.end(), socket);
    if (it != clients_.end())
    {
        clients_.erase(it);
        if (socket->is_open())
        {
            socket->close();
        }
    }
}

bool TcpServerSender::dispose()
{
    stop();
    return true;
}
